package com.example.excel.ui.activity;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;

import com.example.excel.base.BaseViewModel;
import com.example.excel.base.ICallback;
import com.example.excel.bean.BaseBean;
import com.example.excel.bean.InventoryBean;
import com.example.excel.bean.ListBean;
import com.example.excel.config.Constants;
import com.example.excel.db.InventoryController;
import com.example.excel.http.ApiException;
import com.example.excel.http.HttpManager;
import com.example.excel.utils.SharedPreferencesUtils;
import com.example.excel.utils.Utils;
import com.google.gson.Gson;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Response;

public class MainViewModel extends BaseViewModel {
    private static final String TAG = MainViewModel.class.getSimpleName();
    private int mPageNum = 1;
    public int mTotal = -1;
    private ApiException mException = null;

    public MutableLiveData<String> mShowUI = new MutableLiveData<>();
    public MutableLiveData<Boolean> mLoadSuccess = new MutableLiveData<>();
    public MutableLiveData<Boolean> mUploadSuccess = new MutableLiveData<>();

    public MainViewModel(@NonNull Application application) {
        super(application);
    }

    public void loadInventoryData() {
        mException = null;
        mTotal = -1;
        mPageNum = 1;
        getTxtDialog().setValue("正在下载，请等待...");
        Observable.just(1).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
            @io.reactivex.annotations.NonNull
            @Override
            public ObservableSource<?> apply(@io.reactivex.annotations.NonNull Observable<Object> objectObservable) throws Exception {
                return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
                    @io.reactivex.annotations.NonNull
                    @Override
                    public ObservableSource<?> apply(@io.reactivex.annotations.NonNull Object o) throws Exception {
                        if (mException != null) {
                            // 此处选择发送onError事件以结束轮询，因为可触发下游观察者的onError（）方法回调
                            return Observable.error(mException);
                        }
                        if (mTotal != -1 && mPageNum * Constants.PAGE_SIZE > mTotal) {
                            // 此处选择发送onError事件以结束轮询，因为可触发下游观察者的onError（）方法回调
                            mException = new ApiException(new Throwable("资料下载完成"), 10001);
                            return Observable.error(mException);
                        }
                        if (mTotal == -1) {
                            InventoryController.getInstance().deleteAll();
                        } else {
                            mPageNum += 1;
                        }
                        // 注：此处加入了delay操作符，作用 = 延迟一段时间发送（此处设置 = 2s），以实现轮询间间隔设置
                        return HttpManager.getInstance().getApi().listByFaInventory2(mPageNum, Constants.PAGE_SIZE).map(new Function<Response<BaseBean<ListBean>>, Object>() {
                            @io.reactivex.annotations.NonNull
                            @Override
                            public Object apply(@io.reactivex.annotations.NonNull Response<BaseBean<ListBean>> response) throws Exception {
                                Log.d(TAG, "saveToDb - " + mPageNum);
                                ApiException apiException = null;
                                if (response.isSuccessful()) {
                                    BaseBean<ListBean> body = response.body();
                                    if (body != null) {
                                        int code = body.getCode();
                                        String msg = body.getMsg();
                                        if (code == 0) {
                                            Log.d(TAG, "onSuccess");
                                            ListBean data = body.getData();
                                            if (data != null) {
                                                mTotal = data.getTotal();
                                                List<InventoryBean> inventoryBeans = data.getData();
                                                if (inventoryBeans != null && inventoryBeans.size() > 0) {
                                                    faNo = inventoryBeans.get(0).getFaNo();
                                                    boolean insertInTx = InventoryController.getInstance().insertInTx(inventoryBeans);
                                                    if (!insertInTx) {
                                                        apiException = new ApiException(new Throwable("数据库数据插入失败！"), -1);
                                                    }
                                                } else {
                                                    apiException = new ApiException(new Throwable("获取盘点资料为空."), code);
                                                }
                                            } else {
                                                apiException = new ApiException(new Throwable(msg), code);
                                            }
                                        } else {
                                            apiException = new ApiException(new Throwable(msg), code);
                                        }
                                    } else {
                                        apiException = new ApiException(new Throwable(), ApiException.ERROR.UNKNOWN);
                                    }
                                } else {
                                    try {
                                        assert response.errorBody() != null;
                                        String string = response.errorBody().string();
                                        apiException = new ApiException(new Throwable(string), response.code());
                                    } catch (IOException e) {
                                        apiException = new ApiException(new Throwable(e.getMessage()), response.code());
                                    }
                                }
                                if (apiException != null) {
                                    mException = apiException;
                                    Log.d(TAG, "error" + apiException.getMessage());
                                    Log.d(TAG, "轮询结束");
                                }
                                return 0;
                            }
                        });
                    }
                });
            }
        }).subscribeOn(Schedulers.io())               // 切换到IO线程进行网络请求
                .observeOn(AndroidSchedulers.mainThread())  // 切换回到主线程 处理请求结果
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@io.reactivex.annotations.NonNull Integer integer) {

                    }

                    @Override
                    public void onError(@io.reactivex.annotations.NonNull Throwable e) {
                        getDialog().setValue(false);
                        if (!TextUtils.isEmpty(e.getMessage()) && Objects.requireNonNull(e.getMessage()).contains("token已过期")) {
                            getJumpLogin().setValue(true);
                        }
                        if (e.getMessage().contains("资料下载完成")) {
                            updateByFaState(faNo, "1");
                        } else {
                            Utils.getInstance().showToast(e.getMessage());
                        }
                    }

                    @Override
                    public void onComplete() {
                        getDialog().setValue(false);
                    }
                });
    }

    private List<InventoryBean> mUploadBeans;
    private String faNo;

    public void uploadInventoryData() {
        mException = null;
        mPageNum = 0;
        mTotal = -1;
        mUploadBeans = new ArrayList<>();
        getTxtDialog().setValue("正在上传，请等待...");
        Observable.just(1).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
            @io.reactivex.annotations.NonNull
            @Override
            public ObservableSource<?> apply(@io.reactivex.annotations.NonNull Observable<Object> objectObservable) throws Exception {
                return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
                    @io.reactivex.annotations.NonNull
                    @Override
                    public ObservableSource<?> apply(@io.reactivex.annotations.NonNull Object o) throws Exception {
                        if (mException != null) {
                            return Observable.error(mException);
                        }
                        if (mTotal != -1 && mPageNum * Constants.PAGE_SIZE >= mTotal) {
                            mException = new ApiException(new Throwable("盘点资料上传成功"), 0);
                            return Observable.error(mException);
                        }
                        mUploadBeans = InventoryController.getInstance().queryInventory(mPageNum);
                        if (mUploadBeans == null || mUploadBeans.size() == 0) {
                            mException = new ApiException(new Throwable("暂无盘点上传数据"), 0);
                            return Observable.error(mException);
                        }
                        faNo = mUploadBeans.get(0).getFaNo();
                        String faInventory = new Gson().toJson(mUploadBeans);
                        return HttpManager.getInstance().getApi().updateByFaNo2(faInventory).map(new Function<Response<BaseBean<Object>>, Object>() {
                            @io.reactivex.annotations.NonNull
                            @Override
                            public Object apply(@io.reactivex.annotations.NonNull Response<BaseBean<Object>> response) throws Exception {
                                Log.d(TAG, "saveToDb - " + mPageNum);
                                ApiException apiException = null;
                                if (response.isSuccessful()) {
                                    BaseBean<Object> body = response.body();
                                    if (body != null) {
                                        int code = body.getCode();
                                        String msg = body.getMsg();
                                        if (code == 0) {
                                            mPageNum += 1;
                                            if (mTotal == -1) {
                                                mTotal = mUploadBeans.size();
                                            } else {
                                                mTotal += mUploadBeans.size();
                                            }
                                            Log.d(TAG, "onSuccess");
                                        } else {
                                            apiException = new ApiException(new Throwable(msg), code);
                                        }
                                    } else {
                                        apiException = new ApiException(new Throwable(), ApiException.ERROR.UNKNOWN);
                                    }
                                } else {
                                    try {
                                        assert response.errorBody() != null;
                                        String string = response.errorBody().string();
                                        apiException = new ApiException(new Throwable(string), response.code());
                                    } catch (IOException e) {
                                        apiException = new ApiException(new Throwable(e.getMessage()), response.code());
                                    }
                                }
                                if (apiException != null) {
                                    mException = apiException;
                                    Log.d(TAG, "error" + apiException.getMessage());
                                }
                                return 0;
                            }
                        });
                    }
                });
            }
        }).subscribeOn(Schedulers.io())               // 切换到IO线程进行网络请求
                .observeOn(AndroidSchedulers.mainThread())  // 切换回到主线程 处理请求结果
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@io.reactivex.annotations.NonNull Integer integer) {

                    }

                    @Override
                    public void onError(@io.reactivex.annotations.NonNull Throwable e) {
                        getDialog().setValue(false);
                        if (!TextUtils.isEmpty(e.getMessage()) && Objects.requireNonNull(e.getMessage()).contains("token已过期")) {
                            getJumpLogin().setValue(true);
                        }
                        if (e.getMessage().contains("盘点资料上传成功")) {
                            updateByFaStateUpload(faNo, "2");
                        } else {
                            Utils.getInstance().showToast(e.getMessage());
                        }
                    }

                    @Override
                    public void onComplete() {
                        getDialog().setValue(false);
                    }
                });
    }

    public void clear() {
        Observable.just(1).map(new Function<Integer, Boolean>() {
            @io.reactivex.annotations.NonNull
            @Override
            public Boolean apply(@io.reactivex.annotations.NonNull Integer integer) throws Exception {
                return InventoryController.getInstance().deleteAll();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Boolean>() {
            @Override
            public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {

            }

            @Override
            public void onNext(@io.reactivex.annotations.NonNull Boolean aBoolean) {
                if (aBoolean) {
                    SharedPreferencesUtils.setBoolean(Constants.LOAD_COMPLE, false);
                    SharedPreferencesUtils.setBoolean(Constants.UPLOAD_COMPLE, false);
                    mShowUI.setValue("清除本地数据成功");
                } else {
                    mShowUI.setValue("清除本地数据失败，请重新清理");
                }
            }

            @Override
            public void onError(@io.reactivex.annotations.NonNull Throwable e) {
                Utils.getInstance().showToast("e:" + e.getMessage());
            }

            @Override
            public void onComplete() {

            }
        });
    }

    /**
     * @param faState 1盘点中 2 盘点结束
     */
    public void updateByFaState(String faNo, String faState) {
        if (TextUtils.isEmpty(faNo)) {
            Utils.getInstance().showToast("");
            return;
        }
        HttpManager.getInstance().getApi().updateByFaState(faNo, faState).enqueue(new ICallback<Object>(this) {
            @Override
            public void onSuccess(Object o) {
                SharedPreferencesUtils.setBoolean(Constants.LOAD_COMPLE, true);
                mLoadSuccess.setValue(true);
            }

            @Override
            public void onError(ApiException e) {
                mLoadSuccess.setValue(false);
            }
        });
    }

    /**
     * @param faState 1盘点中 2 盘点结束
     */
    public void updateByFaStateUpload(String faNo, String faState) {
        HttpManager.getInstance().getApi().updateByFaState(faNo, faState).enqueue(new ICallback<Object>(this) {
            @Override
            public void onSuccess(Object o) {
                SharedPreferencesUtils.setBoolean(Constants.UPLOAD_COMPLE, true);
                mUploadSuccess.setValue(true);
            }

            @Override
            public void onError(ApiException e) {
                mUploadSuccess.setValue(false);
            }
        });
    }
}
